package com.android.project.framework.gl;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import javax.microedition.khronos.opengles.GL10;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.opengl.GLUtils;
import android.util.Log;

import com.android.project.framework.impl.GLGame;
import com.android.project.framework.impl.GLGraphics;
import com.android.project.framework.FileIO;

/*load a bitmap from an asset and create a texture object from it. It also has a
	few convenience methods to bind the texture and dispose of it.*/
public class Texture {
	
	GLGraphics glGraphics;
	FileIO fileIO;
	String fileName;
	int textureId;
	int minFilter;
	int magFilter;
	public int width;
	public int height;
	boolean mipmapped;
	
	
	public Texture(GLGame glGame, String fileName) {
		this(glGame, fileName, false);
	}
	
	public Texture(GLGame glGame, String fileName, boolean mipmapped) {
		this.fileName = fileName;
		this.glGraphics = glGame.getGLGraphics();
		this.fileIO = glGame.getFileIO();
		this.mipmapped = mipmapped;
		load();
		
	}

	public void load() {
		// TODO Auto-generated method stub
		//codice che genera e carica la texture
		GL10 gl = glGraphics.getGl();
		int[] textureIds = new int[1];
		gl.glGenTextures(1, textureIds, 0);
		textureId = textureIds[0];
		Log.d("texture load ",  "" + textureId);
		InputStream in = null;
		
		try {
			in = fileIO.readAssets(fileName);
			Bitmap bitmap = BitmapFactory.decodeStream(in);
			if (mipmapped) {
				createMipmaps(gl, bitmap);
				} else {
					gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
					GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
					setFilters(GL10.GL_NEAREST, GL10.GL_NEAREST);
					gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);
					width = bitmap.getWidth();
		            height = bitmap.getHeight();
		            bitmap.recycle();
				}
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			throw new RuntimeException("Couldn't load texture '" + fileName +"'", e);
		}
		finally{
			try{
				in.close();
			}
			catch (IOException e) {
				
			}
		}
		
		
	}
	
	private void createMipmaps(GL10 gl, Bitmap bitmap) {
		// TODO Auto-generated method stub
		gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
		width = bitmap.getWidth();
		height = bitmap.getHeight();
		setFilters(GL10.GL_LINEAR_MIPMAP_NEAREST, GL10.GL_LINEAR);
		
		int level = 0;
		int newWidth = width;
		int newHeight = height;
		while(true){
			GLUtils.texImage2D(GL10.GL_TEXTURE_2D, level, bitmap, 0);
			newWidth = newWidth / 2;
			newHeight = newHeight / 2;
			if(newWidth <= 0) break;
			Bitmap newBitmap = Bitmap.createBitmap(newWidth, newHeight, bitmap.getConfig());
			Canvas canvas = new Canvas(newBitmap);
			canvas.drawBitmap(bitmap, new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()),
					new Rect(0, 0, newWidth, newHeight), null);
			bitmap.recycle();
			bitmap = newBitmap;
			level++;
			
		}
		gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);
		bitmap.recycle();
	}
	

	public void reload() {
		load();
		bind();
		setFilters(minFilter, magFilter);
		glGraphics.getGl().glBindTexture(GL10.GL_TEXTURE_2D, 0);
	}

	public void bind() {
		// TODO Auto-generated method stub
		
		GL10 gl = glGraphics.getGl();
		gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
		
		
	}

	private void setFilters(int minFilter, int magFilter) {
		// TODO Auto-generated method stub
		this.minFilter = minFilter;
		this.magFilter = magFilter;
		GL10 gl = glGraphics.getGl();
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, minFilter);
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, magFilter);
		
	}
	
	public void dispose() {
		GL10 gl = glGraphics.getGl();
		gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId);
		int[] textureIds = { textureId };
		gl.glDeleteTextures(1, textureIds, 0);
	}

}
